home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- //
- // Copyright (C) 1995, 1996 by Paul S. McCarthy and Eric Sunshine.
- // Written by Paul S. McCarthy and Eric Sunshine.
- // All Rights Reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the authors
- // and its use is governed by the MiscKit license, found in the file
- // "License.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscTableBorder.cc
- //
- // Structure describing border of an MiscTableView.
- //
- // NOTE: many of the sub-arrays in an MiscTableBorder are conditional.
- // They are not guaranteed to be allocated for every instance. They are
- // only allocated when the caller tries to store a value in them.
- //
- // FIXME: Optimization: separate slot-offset calculations from
- // resizing calculations. Many situations only require an offset-
- // update, not a full size recalc.
- //
- // FIXME: Optimization: fold sort-direction together with sort-type
- // into a single array. Encode sort-direction as a single bit.
- //
- // FIXME: Optimization, simplification: Do not maintain all arrays in
- // visual order. Only maintain sizing array (slots[]) in visual order
- // keep all the others in physical order.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // $Id: MiscTableBorder.cc,v 1.11 96/01/13 23:42:07 zarnuk Exp $
- // $Log: MiscTableBorder.cc,v $
- // Revision 1.11 96/01/13 23:42:07 zarnuk
- // MiscCompareCellFunc -> MiscCompareEntryFunc.
- //
- // Revision 1.10 95/11/12 23:20:03 sunshine
- // Fixed bugs where selection manipulation methods were not checking for valid
- // slot. Fixes bug where selectedSlot() was returning "random" and possibly
- // out-of-range values.
- //
- // Revision 1.9 95/10/20 00:12:05 sunshine
- // Was including MiscTableScroll.h with "" instead of <>.
- //
- // Revision 1.8 95/10/19 05:37:11 sunshine
- // Column slots are no longer 'springy' by default.
- //-----------------------------------------------------------------------------
- #ifdef __GNUC__
- # pragma implementation
- #endif
- #include "MiscTableBorder.h"
- #include <misckit/MiscTableScroll.h>
- #include <misckit/MiscTableCell.h>
-
- extern "Objective-C" {
- #import <objc/zone.h>
- #import <appkit/Cell.h>
- #import <appkit/ButtonCell.h>
- }
-
- extern "C" {
- #include <assert.h>
- #include <math.h> // floor()
- #include <stdlib.h>
- #include <string.h>
- }
-
- #define MISC_LIMIT_CHECK(LO,HI)\
- do {\
- assert( 0 <= LO );\
- assert( LO <= HI );\
- assert( HI <= MISC_MAX_PIXELS_SIZE );\
- } while(0)
-
- #define MISC_RANGE_CHECK(X) assert( 0 <= X ); assert( X < num_slots )
- #define MISC_RANGE_CHECK_1(X) assert( 0 <= X ); assert( X <= num_slots )
-
- #define MISC_ENUM_CHECK(E,N) assert((unsigned int)(E) <= (unsigned int)(N))
-
- #define MISC_SLOT_MEMBER(X,M) ((slots != 0) ? slots[X].M : def_slot.M)
- #define MISC_SET_SLOT_MEMBER(X,N,M)\
- do {\
- needs_recalc = true;\
- if (slots == 0) alloc_slots();\
- slots[X].M = N;\
- } while (0)
-
- #define MISC_MAP(M,I) (((M) != 0) ? (M)[I] : I)
-
- #define MISC_DEF_SORT_DIR MISC_SORT_ASCENDING
- #define MISC_DEF_SORT_TYPE MISC_SORT_STRING_CASE_INSENSITIVE
-
- enum MiscShrinkMode
- {
- SPRINGY_ADJ, // adj_size - size Springy slots
- SPRINGY_CORE, // size - min_size Springy slots
- RIGID_ADJ, // adj_size - size Non-springy slots
- RIGID_CORE, // size - min_size Non-springy slots
- SPRINGY_MIN, // min_size - 0 Springy slots
- RIGID_MIN, // min_size - 0 Non-springy slots
- ZERO_SIZE_SLOT
- };
-
- //-----------------------------------------------------------------------------
- // get_prototype
- //-----------------------------------------------------------------------------
- id MiscTableBorder::get_prototype( MiscCoord_V i ) const
- {
- return [owner border:type getDelegateSlotPrototype:visualToPhysical(i)];
- }
-
-
- //-----------------------------------------------------------------------------
- // get_title
- //-----------------------------------------------------------------------------
- char const* MiscTableBorder::get_title( MiscCoord_V i ) const
- {
- return [owner border:type getDelegateSlotTitle:visualToPhysical(i)];
- }
-
-
- //-----------------------------------------------------------------------------
- // setOwner
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setOwner( MiscTableScroll* x )
- {
- owner = x;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // shrink_mode
- //-----------------------------------------------------------------------------
- int MiscTableBorder::shrink_mode( MiscTableSlot& r )
- {
- int x = 0;
- if (r.isSpringy())
- {
- if (r.adj_size > r.size)
- x = (int) SPRINGY_ADJ;
- else if (r.adj_size > r.min_size)
- x = (int) SPRINGY_CORE;
- else if (r.adj_size > 0)
- x = (int) SPRINGY_MIN;
- else
- x = (int) ZERO_SIZE_SLOT;
- }
- else
- {
- if (r.adj_size > r.size)
- x = (int) RIGID_ADJ;
- else if (r.adj_size > r.min_size)
- x = (int) RIGID_CORE;
- else if (r.adj_size > 0)
- x = (int) RIGID_MIN;
- else
- x = (int) ZERO_SIZE_SLOT;
- }
- return x;
- }
-
-
- //-----------------------------------------------------------------------------
- // global_shrink
- //-----------------------------------------------------------------------------
- void MiscTableBorder::global_shrink( MiscPixels total_size )
- {
- MiscPixels excess = total_size - max_total_size;
- MiscPixels amt[ (int) RIGID_MIN + 1 ];
- int i;
-
- for (i = 0; i <= (int) RIGID_MIN; i++)
- amt[i] = 0;
-
- for (i = 0; i < num_slots; i++)
- {
- MiscTableSlot& r = slots[i];
- MiscPixels delta_adj = r.adj_size - r.size;
- MiscPixels delta_core = r.size - r.min_size;
- if (r.isSpringy())
- {
- amt[ SPRINGY_ADJ ] += delta_adj;
- amt[ SPRINGY_CORE ] += delta_core;
- amt[ SPRINGY_MIN ] += r.min_size;
- }
- else
- {
- amt[ RIGID_ADJ ] += delta_adj;
- amt[ RIGID_CORE ] += delta_core;
- amt[ RIGID_MIN ] += r.min_size;
- }
- }
-
- int mode = 0;
- while (mode <= (int) RIGID_MIN && excess > amt[mode])
- {
- excess -= amt[mode];
- mode++;
- }
-
- assert( mode <= (int) RIGID_MIN );
- assert( excess <= amt[mode] );
- assert( 0 < excess );
- assert( 0 < amt[mode] );
-
- double const scaler = double(excess) / double(amt[mode]);
- MiscPixels adj_sum = 0;
-
- for (i = 0; i < num_slots; i++)
- {
- MiscTableSlot& r = slots[i];
- r.offset -= adj_sum;
- MiscPixels const delta_adj = r.adj_size - r.size;
- MiscPixels const delta_core = r.size - r.min_size;
- MiscPixels const delta_min = r.min_size;
- MiscPixels adj = 0;
- MiscPixels factor = 0;
- if (r.isSpringy())
- {
- if (mode > (int) SPRINGY_ADJ) adj += delta_adj;
- if (mode == (int) SPRINGY_ADJ) factor = delta_adj;
- if (mode > (int) SPRINGY_CORE) adj += delta_core;
- if (mode == (int) SPRINGY_CORE) factor = delta_core;
- if (mode > (int) SPRINGY_MIN) adj += delta_min;
- if (mode == (int) SPRINGY_MIN) factor = delta_min;
- }
- else
- {
- if (mode > (int) RIGID_ADJ) adj += delta_adj;
- if (mode == (int) RIGID_ADJ) factor = delta_adj;
- if (mode > (int) RIGID_CORE) adj += delta_core;
- if (mode == (int) RIGID_CORE) factor = delta_core;
- if (mode > (int) RIGID_MIN) adj += delta_min;
- if (mode == (int) RIGID_MIN) factor = delta_min;
- }
- adj += (MiscPixels) floor( double(factor) * scaler );
- if (adj > excess)
- adj = excess;
- excess -= adj;
- r.adj_size -= adj;
- adj_sum += adj;
- }
-
- while (excess > 0)
- {
- adj_sum = 0;
- for (i = 0; i < num_slots; i++)
- {
- MiscTableSlot& r = slots[i];
- r.offset -= adj_sum;
- if (excess > 0)
- {
- int rank = shrink_mode( r );
- if (rank <= mode)
- {
- r.adj_size--;
- excess--;
- adj_sum++;
- }
- }
- }
- assert( adj_sum > 0 );
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // find_springy_slot
- //-----------------------------------------------------------------------------
- MiscCoord_V MiscTableBorder::find_springy_slot() const
- {
- assert( num_slots > 0 );
- assert( num_springy > 0 );
- MiscCoord_V const lim = num_slots - 1;
- MiscCoord_V x = 0;
- for ( ; x < lim; x++)
- if (slots[x].isSpringy())
- break;
- return x;
- }
-
-
- //-----------------------------------------------------------------------------
- // global_grow
- //-----------------------------------------------------------------------------
- void MiscTableBorder::global_grow( MiscPixels total_size )
- {
- MiscPixels deficit = min_total_size - total_size;
- if (num_springy > 0)
- {
- if (num_springy == 1)
- {
- MiscCoord_V x = find_springy_slot();
- slots[x].adj_size += deficit;
- while (++x < num_slots)
- slots[x].offset += deficit;
- }
- else // (num_springy > 1)
- {
- MiscCoord_V x;
- MiscPixels springy_sum = 0;
- for (x = 0; x < num_slots; x++)
- if (slots[x].isSpringy())
- springy_sum += slots[x].size;
-
- double scaler = 1;
- if (springy_sum == 0)
- scaler = 1.0 / double(num_springy);
- else
- scaler = double(deficit) / double(springy_sum);
-
- MiscPixels adj_sum = 0;
- for (x = 0; x < num_slots; x++)
- {
- MiscTableSlot& r = slots[x];
- r.offset += adj_sum;
- if (r.isSpringy())
- {
- MiscPixels adj = (MiscPixels)
- floor( double(r.size) * scaler );
- if (adj > deficit)
- adj = deficit;
- deficit -= adj;
- r.adj_size += adj;
- adj_sum += adj;
- }
- }
-
- while (deficit > 0)
- {
- adj_sum = 0;
- for (x = 0; x < num_slots; x++)
- {
- MiscTableSlot& r = slots[x];
- r.offset += adj_sum;
- if (r.isSpringy() && deficit > 0)
- {
- deficit--;
- r.adj_size++;
- adj_sum++;
- }
- }
- assert( adj_sum != 0 );
- }
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // perform_recalc
- //-----------------------------------------------------------------------------
- void MiscTableBorder::perform_recalc()
- {
- MISC_LIMIT_CHECK( min_total_size, max_total_size );
-
- int i;
- MiscPixels total_size = 0;
-
- if (slots == 0)
- alloc_slots();
-
- for (i = 0; i < num_slots; i++)
- {
- MiscTableSlot& r = slots[i];
- assert( 0 <= r.min_size );
- assert( r.min_size <= r.size );
- assert( r.size <= r.max_size );
- assert( r.max_size <= MISC_MAX_PIXELS_SIZE );
- r.offset = total_size;
- r.adj_size = r.size;
- if (r.isData() && r.adj_size < r.data_size)
- {
- r.adj_size = r.data_size;
- if (r.adj_size > r.max_size)
- r.adj_size = r.max_size;
- }
- total_size += r.adj_size;
- }
-
- if (total_size < min_total_size)
- global_grow( total_size );
-
- else if (total_size > max_total_size)
- global_shrink( total_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // do_recalc
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_recalc()
- {
- needs_recalc = false;
- if (uniform_size == 0 && num_slots > 0)
- perform_recalc();
- }
-
-
- //-----------------------------------------------------------------------------
- // recalc_if_needed
- //-----------------------------------------------------------------------------
- inline void MiscTableBorder::recalc_if_needed()
- {
- if (needs_recalc)
- do_recalc();
- }
-
-
- //-----------------------------------------------------------------------------
- // recalcOffsets
- //-----------------------------------------------------------------------------
- void MiscTableBorder::recalcOffsets()
- {
- needs_recalc = true;
- recalc_if_needed();
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_size
- //-----------------------------------------------------------------------------
- inline int MiscTableBorder::alloc_size( int rec_size )
- {
- return rec_size * max_slots;
- }
-
-
- //-----------------------------------------------------------------------------
- // do_alloc
- //-----------------------------------------------------------------------------
- void* MiscTableBorder::do_alloc( int size )
- {
- return malloc( alloc_size(size) );
- }
-
-
-
- //-----------------------------------------------------------------------------
- // do_alloc_init
- //-----------------------------------------------------------------------------
- void* MiscTableBorder::do_alloc_init( int size )
- {
- int const nbytes = alloc_size( size );
- void* const p = malloc( nbytes );
- memset( p, 0, nbytes );
- return p;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // do_realloc
- //-----------------------------------------------------------------------------
- void* MiscTableBorder::do_realloc( void* p, int size )
- {
- if (p != 0)
- {
- if (max_slots != 0)
- {
- p = realloc( p, max_slots * size );
- }
- else
- {
- free( p );
- p = 0;
- }
- }
- return p;
- }
-
-
- //-----------------------------------------------------------------------------
- // do_realloc
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_realloc()
- {
- slots = (MiscTableSlot*) do_realloc( slots, sizeof(*slots) );
- v2p = (MiscCoord_P*) do_realloc( v2p, sizeof(*v2p) );
- p2v = (MiscCoord_V*) do_realloc( p2v, sizeof(*p2v) );
- tags = (int*) do_realloc( tags, sizeof(*tags) );
- titles = (char**) do_realloc( titles, sizeof(*titles) );
- styles = (MiscTableCellStyle*) do_realloc( styles, sizeof(*styles) );
- prototypes = (id*) do_realloc( prototypes, sizeof(*prototypes) );
- sort_funcs = (MiscCompareEntryFunc*)
- do_realloc( sort_funcs, sizeof(*sort_funcs) );
- sort_dirs = (MiscSortDirection*) do_realloc(sort_dirs,sizeof(*sort_dirs));
- sort_types = (MiscSortType*) do_realloc( sort_types, sizeof(*sort_types) );
- }
-
-
- //-----------------------------------------------------------------------------
- // freeExtraCapacity
- //-----------------------------------------------------------------------------
- void MiscTableBorder::freeExtraCapacity()
- {
- if (max_slots > num_slots)
- {
- max_slots = num_slots;
- do_realloc();
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // setCapacity
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setCapacity( int x )
- {
- if (max_slots < x)
- {
- max_slots = x;
- do_realloc();
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // empty
- //-----------------------------------------------------------------------------
- void MiscTableBorder::empty()
- {
- setCount(0);
- selectNone();
- clearCursor();
- }
-
-
-
- //-----------------------------------------------------------------------------
- // init_slot
- //-----------------------------------------------------------------------------
- void MiscTableBorder::init_slot( MiscCoord_V x, MiscCoord_P p )
- {
- if (def_slot.isSpringy())
- num_springy++;
-
- if (slots != 0)
- slots[x] = def_slot;
-
- if (tags != 0)
- tags[x] = def_tag;
-
- if (titles != 0)
- titles[x] = 0;
-
- if (styles != 0)
- styles[x] = def_style;
-
- if (prototypes != 0)
- prototypes[x] = 0;
-
- if (sort_funcs != 0)
- sort_funcs[x] = 0;
-
- if (sort_dirs != 0)
- sort_dirs[x] = MISC_DEF_SORT_DIR;
-
- if (sort_types != 0)
- sort_types[x] = MISC_DEF_SORT_TYPE;
-
- if (v2p != 0)
- {
- v2p[x] = p;
- p2v[p] = x;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // destroy_slot
- //-----------------------------------------------------------------------------
- void MiscTableBorder::destroy_slot( MiscCoord_V x )
- {
- if (isSpringy(x))
- num_springy--;
-
- if (titles != 0 && titles[x] != 0)
- free( titles[x] );
-
- if (prototypes != 0 && prototypes[x] != 0)
- [prototypes[x] free];
- }
-
-
- //-----------------------------------------------------------------------------
- // do_delete
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_delete( void* p, int i, int n )
- {
- if (p != 0)
- memmove( p + i * n, p + (i + 1) * n, (num_slots - i) * n );
- }
-
-
- //-----------------------------------------------------------------------------
- // do_delete
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_delete( MiscCoord_V x, MiscCoord_P p )
- {
- if (x < num_slots)
- {
- do_delete( slots, x, sizeof(*slots) );
- do_delete( v2p, x, sizeof(*v2p) );
- do_delete( tags, x, sizeof(*tags) );
- do_delete( titles, x, sizeof(*titles) );
- do_delete( styles, x, sizeof(*styles) );
- do_delete( prototypes, x, sizeof(*prototypes) );
- do_delete( sort_funcs, x, sizeof(*sort_funcs) );
- do_delete( sort_dirs, x, sizeof(*sort_dirs) );
- do_delete( sort_types, x, sizeof(*sort_types) );
- }
- if (p < num_slots)
- do_delete( p2v, p, sizeof(*p2v) );
- }
-
-
- //-----------------------------------------------------------------------------
- // deleteAt
- //-----------------------------------------------------------------------------
- void MiscTableBorder::deleteAt( MiscCoord_V x )
- {
- MISC_RANGE_CHECK( x );
-
- selection.shiftDownAt( x );
- if (num_slots <= 1)
- clearCursor();
-
- needs_recalc = true;
-
- MiscCoord_P const p = visualToPhysical(x);
-
- destroy_slot( x );
-
- num_slots--;
- do_delete( x, p );
-
- if (v2p != 0)
- {
- for (int i = 0; i < num_slots; i++)
- {
- if (v2p[i] >= p)
- v2p[i]--;
- if (p2v[i] >= x)
- p2v[i]--;
- }
- }
-
- }
-
-
- //-----------------------------------------------------------------------------
- // do_insert
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_insert( void* p, int i, int n )
- {
- if (p != 0)
- memmove( p + (i + 1) * n, p + i * n, (num_slots - i) * n );
- }
-
-
- //-----------------------------------------------------------------------------
- // do_insert
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_insert( MiscCoord_V x, MiscCoord_P p )
- {
- if (x < num_slots)
- {
- do_insert( slots, x, sizeof(*slots) );
- do_insert( v2p, x, sizeof(*v2p) );
- do_insert( tags, x, sizeof(*tags) );
- do_insert( titles, x, sizeof(*titles) );
- do_insert( styles, x, sizeof(*styles) );
- do_insert( prototypes, x, sizeof(*prototypes) );
- do_insert( sort_funcs, x, sizeof(*sort_funcs) );
- do_insert( sort_dirs, x, sizeof(*sort_dirs) );
- do_insert( sort_types, x, sizeof(*sort_types) );
- }
-
- if (p < num_slots)
- do_insert( p2v, p, sizeof(*p2v) );
- }
-
-
- //-----------------------------------------------------------------------------
- // insertAt
- //-----------------------------------------------------------------------------
- void MiscTableBorder::insertAt( MiscCoord_V x, MiscCoord_P p )
- {
- MISC_RANGE_CHECK_1( x );
-
- needs_recalc = true;
-
- if (num_slots >= max_slots)
- setCapacity( max_slots + 1 );
-
- do_insert( x, p );
-
- if (v2p != 0)
- {
- for (int i = 0; i < num_slots; i++)
- {
- if (p2v[i] >= x)
- p2v[i]++;
- if (v2p[i] >= p)
- v2p[i]++;
- }
- }
-
- init_slot( x, p );
-
- num_slots++;
-
- selection.shiftUpAt( x );
- if (hasValidCursor() && cursor >= x)
- cursor++;
- }
-
-
- //-----------------------------------------------------------------------------
- // do_shift
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_shift( void* p, int i, int j, int n )
- {
- if (p != 0)
- {
- if (i < j)
- memmove( p + i * n, p + (i + 1) * n, (j - i) * n );
- else
- memmove( p + (j + 1) * n, p + j * n, (i - j) * n );
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // do_shift
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_shift( MiscCoord_V from, MiscCoord_V to )
- {
- do_shift( slots, from, to, sizeof(*slots) );
- do_shift( v2p, from, to, sizeof(*v2p) );
- do_shift( tags, from, to, sizeof(*tags) );
- do_shift( titles, from, to, sizeof(*titles) );
- do_shift( styles, from, to, sizeof(*styles) );
- do_shift( prototypes, from, to, sizeof(*prototypes) );
- do_shift( sort_funcs, from, to, sizeof(*sort_funcs) );
- do_shift( sort_dirs, from, to, sizeof(*sort_dirs) );
- do_shift( sort_types, from, to, sizeof(*sort_types) );
- }
-
-
- //-----------------------------------------------------------------------------
- // alloc_vmap
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_vmap()
- {
- p2v = (MiscCoord_V*) do_alloc( sizeof(*p2v) );
- v2p = (MiscCoord_P*) do_alloc( sizeof(*v2p) );
- for (int i = 0; i < num_slots; i++)
- {
- p2v[i] = i;
- v2p[i] = i;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // moveFromTo
- //-----------------------------------------------------------------------------
- void MiscTableBorder::moveFromTo( MiscCoord_V from, MiscCoord_V to )
- {
- MISC_RANGE_CHECK( from ); MISC_RANGE_CHECK( to );
-
- bool const was_cursor = (hasValidCursor() && cursor == from);
- bool const was_selected = selection.contains( from );
- selection.shiftDownAt( from );
-
- needs_recalc = true;
-
- MiscCoord_P const p = visualToPhysical( from );
- MiscTableSlot const tmp_slot = slots ? slots[from] : def_slot;
- int const tmp_tag = (tags ? tags[from] : def_tag);
- char* const tmp_title = (titles ? titles[from] : 0);
- MiscTableCellStyle tmp_style = (styles ? styles[from] : def_style);
- id tmp_prototype = (prototypes ? prototypes[from] : 0);
- MiscCompareEntryFunc const tmp_func = (sort_funcs ? sort_funcs[from] : 0);
- MiscSortDirection tmp_dir =
- (sort_dirs ? sort_dirs[from] : MISC_SORT_ASCENDING);
- MiscSortType tmp_type =
- (sort_types ? sort_types[from] : MISC_SORT_STRING_CASE_INSENSITIVE);
-
- if (p2v == 0)
- alloc_vmap();
-
- do_shift( from, to );
-
- if (from < to)
- {
- for (int i = 0; i < num_slots; i++)
- if (from < p2v[i] && p2v[i] <= to)
- p2v[i]--;
- if (!was_cursor && from <= cursor && cursor >= to)
- cursor--;
- }
- else
- {
- for (int i = 0; i < num_slots; i++)
- if (to <= p2v[i] && p2v[i] < from)
- p2v[i]++;
- if (!was_cursor && from <= cursor && cursor >= to)
- cursor++;
- }
- p2v[p] = to;
- v2p[to] = p;
-
- if (slots != 0) slots[to] = tmp_slot;
- if (tags != 0) tags[to] = tmp_tag;
- if (titles != 0) titles[to] = tmp_title;
- if (styles != 0) styles[to] = tmp_style;
- if (prototypes != 0) prototypes[to] = tmp_prototype;
- if (sort_funcs != 0) sort_funcs[to] = tmp_func;
- if (sort_dirs != 0) sort_dirs[to] = tmp_dir;
- if (sort_types != 0) sort_types[to] = tmp_type;
-
- selection.shiftUpAt( to );
- if (was_selected)
- selection.add( to );
- if (was_cursor)
- cursor = to;
- }
-
-
- //-----------------------------------------------------------------------------
- // setCount
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setCount( int x )
- {
- setVMap(0);
- if (num_slots != x)
- {
- needs_recalc = true;
- int const old_slots = num_slots;
- num_slots = x;
- setCapacity( x ); // Only increases capacity, never decreases.
-
- if (old_slots < num_slots)
- {
- for (int i = old_slots; i < num_slots; i++)
- init_slot( i, i );
- }
- else
- {
- assert( old_slots <= max_slots );
- num_slots = old_slots;
- for (int i = x; i < old_slots; i++)
- destroy_slot( i );
- num_slots = x;
-
- selection.remove( num_slots, old_slots );
- if (cursor >= num_slots) selectNone();
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // good_int_map
- // 'map' is a good map if all the values are in-range, and no value
- // is repeated. A null map represents a normal sequential series.
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::good_int_map( int const* map ) const
- {
- bool answer = true;
- int const lim = count();
- if (lim > 0)
- {
- if (map != 0)
- {
- bool* seen = (bool*) calloc( sizeof(bool), lim );
- for (int i = 0; i < lim; i++)
- {
- int const x = map[i];
- if ((unsigned int) x < (unsigned int)lim && !seen[i])
- seen[i] = true;
- else
- {
- answer = false;
- break;
- }
- }
- free( seen );
- }
- }
- return answer;
- }
-
-
- //-----------------------------------------------------------------------------
- // goodVMap
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::goodVMap( MiscCoord_V const* map ) const
- {
- return good_int_map( (int const*) map );
- }
-
-
- //-----------------------------------------------------------------------------
- // goodPMap
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::goodPMap( MiscCoord_P const* map ) const
- {
- return good_int_map( (int const*) map );
- }
-
-
- //-----------------------------------------------------------------------------
- // do_remap
- //-----------------------------------------------------------------------------
- void* MiscTableBorder::do_remap( void* p, int n, MiscCoord_V const* new_p2v )
- {
- if (p != 0)
- {
- void* t = do_alloc( n );
- for (int i = 0; i < num_slots; i++)
- memcpy( t + MISC_MAP(new_p2v,i) * n,
- p + MISC_MAP(p2v,i) * n, n );
- free( p );
- p = t;
- }
- return p;
- }
-
-
- //-----------------------------------------------------------------------------
- // do_remap
- //-----------------------------------------------------------------------------
- void MiscTableBorder::do_remap( MiscCoord_V const* new_p2v )
- {
- if (num_slots > 0)
- {
- slots = (MiscTableSlot*)
- do_remap( slots, sizeof(*slots), new_p2v );
- tags = (int*)
- do_remap( tags, sizeof(*tags), new_p2v );
- titles = (char**)
- do_remap( titles, sizeof(*titles), new_p2v );
- styles = (MiscTableCellStyle*)
- do_remap( styles, sizeof(*styles), new_p2v );
- prototypes = (id*)
- do_remap( prototypes, sizeof(*prototypes), new_p2v );
- sort_funcs = (MiscCompareEntryFunc*)
- do_remap( sort_funcs, sizeof(*sort_funcs), new_p2v );
- sort_dirs = (MiscSortDirection*)
- do_remap( sort_dirs, sizeof(*sort_dirs), new_p2v );
- sort_types = (MiscSortType*)
- do_remap( sort_types, sizeof(*sort_types), new_p2v );
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // setVMap
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::setVMap( MiscCoord_V const* new_p2v )
- {
- if (goodVMap( new_p2v ))
- {
- if (new_p2v != 0 || p2v != 0)
- {
- needs_recalc = true;
- do_remap( new_p2v );
- if (p2v == 0)
- {
- p2v = (MiscCoord_V*) do_alloc( sizeof(*p2v) );
- v2p = (MiscCoord_P*) do_alloc( sizeof(*v2p) );
- }
- if (new_p2v != 0 && p2v != 0)
- {
- for (int i = 0; i < num_slots; i++)
- v2p[new_p2v[i]] = i;
- memcpy( p2v, new_p2v, num_slots * sizeof(*p2v) );
- }
- else if (new_p2v == 0)
- {
- free( p2v ); p2v = 0;
- free( v2p ); v2p = 0;
- }
- }
- return true;
- }
- return false;
- }
-
-
- //-----------------------------------------------------------------------------
- // setPMap
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::setPMap( MiscCoord_P const* new_v2p )
- {
- if (goodPMap( new_v2p ))
- {
- if (new_v2p != 0 || v2p != 0)
- {
- if (new_v2p != 0)
- {
- MiscCoord_V* new_p2v =
- (MiscCoord_V*) malloc( sizeof(*new_p2v) * num_slots );
- for (int i = 0; i < num_slots; i++)
- new_p2v[new_v2p[i]] = i;
- setVMap( new_p2v );
- free( new_p2v );
- }
- else
- setVMap( 0 );
- }
- return true;
- }
- return false;
- }
-
-
- //-----------------------------------------------------------------------------
- // clearVMap
- //-----------------------------------------------------------------------------
- void MiscTableBorder::clearVMap()
- {
- if (v2p != 0) { free( v2p ); v2p = 0; }
- if (p2v != 0) { free( p2v ); p2v = 0; }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // setUniformSize
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::setUniformSize( MiscPixels x )
- {
- bool const changed = (uniform_size != x);
- if (changed)
- {
- needs_recalc = true;
- if (uniform_size == 0) // New, non-zero uniform size.
- {
- if (slots != 0)
- { free( slots ); slots = 0; }
- min_total_size = 0;
- max_total_size = MISC_MAX_PIXELS_SIZE;
- }
- uniform_size = x;
- }
- return changed;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // setTitleMode
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::setTitleMode( MiscTableTitleMode x )
- {
- MISC_ENUM_CHECK( x, MISC_MAX_TITLE );
- bool const changed = (title_mode != x);
- if (changed)
- {
- dealloc_titles();
- title_mode = x;
- }
- return changed;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // totalSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::totalSize()
- {
- if (num_slots == 0)
- return 0;
- else if (uniform_size)
- return (uniform_size * num_slots);
- else
- {
- recalc_if_needed();
- return getOffset( num_slots - 1 ) + effectiveSize( num_slots - 1 );
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // setMinTotalSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setMinTotalSize( MiscPixels x )
- {
- if (min_total_size != x)
- {
- needs_recalc = true;
- min_total_size = x;
- if (max_total_size < min_total_size)
- max_total_size = min_total_size;
- assert( 0 <= min_total_size );
- assert( min_total_size <= max_total_size );
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // setMaxTotalSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setMaxTotalSize( MiscPixels x )
- {
- if (max_total_size != x)
- {
- needs_recalc = true;
- max_total_size = x;
- if (min_total_size > max_total_size)
- min_total_size = max_total_size;
- assert( min_total_size <= max_total_size );
- assert( max_total_size <= MISC_MAX_PIXELS_SIZE );
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // find_slot_for_offset
- //-----------------------------------------------------------------------------
- MiscCoord_V MiscTableBorder::find_slot_for_offset( MiscPixels x )
- {
- assert( num_slots > 0 );
- int lo = 0;
- int hi = num_slots - 1;
- while (lo <= hi)
- {
- int const mid = (lo + hi) >> 1;
- if (slots[mid].offset <= x)
- lo = mid + 1;
- else
- hi = mid - 1;
- }
- if (lo > 0 && (lo >= num_slots || slots[lo].offset > x))
- lo--;
- return lo;
- }
-
-
- //-----------------------------------------------------------------------------
- // visualForOffset
- //-----------------------------------------------------------------------------
- MiscCoord_V MiscTableBorder::visualForOffset( MiscPixels x )
- {
- MiscCoord_V i = -1;
- if (x >= 0 && num_slots > 0)
- {
- if (uniform_size != 0)
- {
- i = (MiscCoord_V) (x / uniform_size);
- }
- else
- {
- recalc_if_needed();
- i = find_slot_for_offset( x );
- }
- }
- if (i >= num_slots)
- i = num_slots - 1;
- return i;
- }
-
-
- //-----------------------------------------------------------------------------
- // getOffset
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::getOffset( MiscCoord_V x )
- {
- if (num_slots == 0)
- return 0;
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size * x;
- recalc_if_needed();
- return MISC_SLOT_MEMBER( x, offset );
- }
-
-
- //-----------------------------------------------------------------------------
- // getSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::getSize( MiscCoord_V x ) const
- {
- if (num_slots == 0)
- return 0;
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
- return MISC_SLOT_MEMBER( x, size );
- }
-
-
- //-----------------------------------------------------------------------------
- // getMinSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::getMinSize( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
- return MISC_SLOT_MEMBER( x, min_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // getMaxSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::getMaxSize( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
- return MISC_SLOT_MEMBER( x, max_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // getDataSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::getDataSize( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
- return MISC_SLOT_MEMBER( x, data_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // effectiveSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::effectiveSize( MiscCoord_V x )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
- recalc_if_needed();
- return MISC_SLOT_MEMBER( x, adj_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // effectiveMaxSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::effectiveMaxSize( MiscCoord_V x )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
-
- recalc_if_needed();
-
- MiscTableSlot const& r = slots[x];
- MiscPixels slot_max = r.max_size;
-
- MiscPixels global_max = max_total_size;
-
- for (int i = 0; i < num_slots; i++)
- {
- if (i != x)
- {
- MiscTableSlot& t = slots[i];
- if (t.isSpringy())
- global_max -= t.min_size;
- else
- global_max -= t.size;
- }
- }
-
- if (slot_max > global_max)
- slot_max = global_max;
-
- return slot_max;
- }
-
-
- //-----------------------------------------------------------------------------
- // effectiveMinSize
- //-----------------------------------------------------------------------------
- MiscPixels MiscTableBorder::effectiveMinSize( MiscCoord_V x )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return uniform_size;
-
- recalc_if_needed();
-
- MiscTableSlot const& r = slots[x];
- MiscPixels slot_min = r.min_size;
-
- MiscPixels global_min = min_total_size;
-
- for (int i = 0; i < num_slots; i++)
- {
- if (i != x)
- {
- MiscTableSlot& t = slots[i];
- if (t.isSpringy())
- global_min -= t.max_size;
- else
- global_min -= t.size;
- }
- }
-
- if (slot_min < global_min)
- slot_min = global_min;
-
- if (slot_min > r.adj_size)
- slot_min = r.adj_size;
-
- return slot_min;
- }
-
-
- //-----------------------------------------------------------------------------
- // getSizing
- //-----------------------------------------------------------------------------
- MiscTableSizing MiscTableBorder::getSizing( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size != 0)
- return MISC_NUSER_NDATA_NSPRINGY_SIZING;
- return MISC_SLOT_MEMBER( x, sizing );
- }
-
-
- //-----------------------------------------------------------------------------
- // alpha_title
- //-----------------------------------------------------------------------------
- static char* alpha_title( char* p, int x )
- {
- *--p = '\0';
- if (x >= 26)
- {
- do {
- *--p = (x % 26) + 'A';
- x /= 26;
- }
- while (x >= 26);
- x--;
- }
- *--p = x + 'A';
- return p;
- }
-
-
- //-----------------------------------------------------------------------------
- // getTitle
- //-----------------------------------------------------------------------------
- char const* MiscTableBorder::getTitle( MiscCoord_V x ) const
- {
- int const BUFF_LEN = 16;
- static char buff[ BUFF_LEN ];
- char const* s = "";
- MISC_RANGE_CHECK( x );
- switch (title_mode)
- {
- case MISC_NO_TITLE:
- break;
- case MISC_NUMBER_TITLE:
- sprintf( buff, "%d", visualToPhysical(x) + 1 );
- s = buff;
- break;
- case MISC_ALPHA_TITLE:
- s = alpha_title( buff + BUFF_LEN, visualToPhysical(x) );
- break;
- case MISC_CUSTOM_TITLE:
- s = (titles != 0) ? titles[x] : "";
- break;
- case MISC_DELEGATE_TITLE:
- s = get_title( x );
- break;
- }
- return s;
- }
-
-
- //-----------------------------------------------------------------------------
- // getTag
- //-----------------------------------------------------------------------------
- int MiscTableBorder::getTag( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- return (tags != 0) ? tags[x] : def_tag;
- }
-
-
- //-----------------------------------------------------------------------------
- // getStyle
- //-----------------------------------------------------------------------------
- MiscTableCellStyle MiscTableBorder::getStyle( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- return (styles != 0) ? styles[x] : def_style;
- }
-
-
- //-----------------------------------------------------------------------------
- // getSortFunc
- //-----------------------------------------------------------------------------
- MiscCompareEntryFunc MiscTableBorder::getSortFunc( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- return (sort_funcs != 0) ? sort_funcs[x] : 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // getSortDirection
- //-----------------------------------------------------------------------------
- MiscSortDirection MiscTableBorder::getSortDirection( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- return (sort_dirs != 0) ? sort_dirs[x] : MISC_SORT_ASCENDING;
- }
-
-
- //-----------------------------------------------------------------------------
- // getSortType
- //-----------------------------------------------------------------------------
- MiscSortType MiscTableBorder::getSortType( MiscCoord_V x ) const
- {
- MISC_RANGE_CHECK( x );
- return (sort_types != 0) ? sort_types[x] :
- MISC_SORT_STRING_CASE_INSENSITIVE;
- }
-
-
- //-----------------------------------------------------------------------------
- // alloc_prototypes
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_prototypes()
- {
- prototypes = (id*) do_alloc_init( sizeof(*prototypes) );
- }
-
-
- //-----------------------------------------------------------------------------
- // new_prototype
- //-----------------------------------------------------------------------------
- id MiscTableBorder::new_prototype( MiscCoord_V x )
- {
- NXZone* const zone = [owner zone];
- id p = 0;
- switch (getStyle(x))
- {
- case MISC_TABLE_CELL_TEXT:
- p = [[MiscTableCell allocFromZone:zone] initTextCell:0];
- break;
- case MISC_TABLE_CELL_ICON:
- p = [[MiscTableCell allocFromZone:zone] initIconCell:0];
- break;
- case MISC_TABLE_CELL_BUTTON:
- p = [[ButtonCell allocFromZone:zone] initTextCell:0];
- break;
- case MISC_TABLE_CELL_CALLBACK:
- p = get_prototype(x);
- break;
- }
- return p;
- }
-
-
- //-----------------------------------------------------------------------------
- // getPrototype
- //-----------------------------------------------------------------------------
- id MiscTableBorder::getPrototype( MiscCoord_V x )
- {
- MISC_RANGE_CHECK( x );
- if (prototypes == 0)
- alloc_prototypes();
- id p = prototypes[x];
- if (p == 0)
- p = prototypes[x] = new_prototype(x);
- return p;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_slots
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_slots()
- {
- assert( slots == 0 );
- slots = (MiscTableSlot*) do_alloc( sizeof(*slots) );
- for (int i = 0; i < num_slots; i++)
- slots[i] = def_slot;
- }
-
-
- //-----------------------------------------------------------------------------
- // setSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setSize( MiscCoord_V x, MiscPixels n )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size == 0)
- MISC_SET_SLOT_MEMBER( x, n, size );
- }
-
-
- //-----------------------------------------------------------------------------
- // setMinSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setMinSize( MiscCoord_V x, MiscPixels n )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size == 0)
- MISC_SET_SLOT_MEMBER( x, n, min_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // setMaxSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setMaxSize( MiscCoord_V x, MiscPixels n )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size == 0)
- MISC_SET_SLOT_MEMBER( x, n, max_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // setDataSize
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setDataSize( MiscCoord_V x, MiscPixels n )
- {
- MISC_RANGE_CHECK( x );
- if (uniform_size == 0)
- MISC_SET_SLOT_MEMBER( x, n, data_size );
- }
-
-
- //-----------------------------------------------------------------------------
- // setSizing
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setSizing( MiscCoord_V x, MiscTableSizing n )
- {
- MISC_RANGE_CHECK( x );
- MISC_ENUM_CHECK( n, MISC_MAX_SIZING );
- if (uniform_size == 0)
- {
- bool was_springy = ::isSpringy(getSizing(x));
- bool is_springy = ::isSpringy(n);
- if (was_springy != is_springy)
- {
- if (was_springy)
- num_springy--;
- else
- num_springy++;
- }
- MISC_SET_SLOT_MEMBER( x, n, sizing );
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // dealloc_titles
- //-----------------------------------------------------------------------------
- void MiscTableBorder::dealloc_titles()
- {
- if (titles != 0)
- {
- for (int i = 0; i < num_slots; i++)
- if (titles[i] != 0)
- free( titles[i] );
- free( titles );
- titles = 0;
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_titles
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_titles()
- {
- titles = (char**) do_alloc_init( sizeof(*titles) );
- }
-
-
- //-----------------------------------------------------------------------------
- // do_strdup
- //-----------------------------------------------------------------------------
- static char* do_strdup( char const* s )
- {
- char* p = 0;
- if (s != 0 && *s != 0)
- strcpy( p = (char*) malloc( strlen(s) + 1 ), s );
- return p;
- }
-
-
- //-----------------------------------------------------------------------------
- // setTitle
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::setTitle( MiscCoord_V x, char const* s )
- {
- bool changed = false;
- if (getTitleMode() == MISC_CUSTOM_TITLE)
- {
- MISC_RANGE_CHECK( x );
- char* const t = (titles ? titles[x] : 0);
- if (t != 0 || s != 0)
- {
- if (t == 0 || s == 0 || strcmp(t,s) != 0)
- {
- if (t != 0) free(t);
- if (titles == 0) alloc_titles();
- titles[x] = do_strdup(s);
- changed = true;
- }
- }
- }
- return changed;
- }
-
-
- //-----------------------------------------------------------------------------
- // alloc_tags
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_tags()
- {
- tags = (int*) do_alloc_init( sizeof(*tags) );
- if (def_tag != 0)
- for (int i = 0; i < num_slots; i++)
- tags[i] = def_tag;
- }
-
-
- //-----------------------------------------------------------------------------
- // setTag
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setTag( MiscCoord_V x, int n )
- {
- MISC_RANGE_CHECK( x );
- if (tags == 0) alloc_tags();
- tags[x] = n;
- }
-
-
- //-----------------------------------------------------------------------------
- // alloc_styles
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_styles()
- {
- styles = (MiscTableCellStyle*) do_alloc_init( sizeof(*styles) );
- if ((int) def_style != 0)
- for (int i = 0; i < num_slots; i++)
- styles[i] = def_style;
- }
-
-
- //-----------------------------------------------------------------------------
- // setStyle
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setStyle( MiscCoord_V x, MiscTableCellStyle n )
- {
- MISC_RANGE_CHECK( x );
- MISC_ENUM_CHECK( n, MISC_TABLE_CELL_MAX );
- if (styles == 0) alloc_styles();
- styles[x] = n;
- }
-
-
- //-----------------------------------------------------------------------------
- // setPrototype
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setPrototype( MiscCoord_V x, id n )
- {
- MISC_RANGE_CHECK( x );
- if (prototypes == 0) alloc_prototypes();
- if (prototypes[x] != 0)
- [prototypes[x] free];
- prototypes[x] = n;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_sort_funcs
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_sort_funcs()
- {
- sort_funcs = (MiscCompareEntryFunc*) do_alloc_init( sizeof(*sort_funcs) );
- }
-
-
- //-----------------------------------------------------------------------------
- // setSortFunc
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setSortFunc( MiscCoord_V x, MiscCompareEntryFunc n )
- {
- MISC_RANGE_CHECK( x );
- if (sort_funcs == 0) alloc_sort_funcs();
- sort_funcs[x] = n;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_sort_dirs
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_sort_dirs()
- {
- sort_dirs = (MiscSortDirection*) do_alloc_init( sizeof(*sort_dirs) );
- }
-
-
- //-----------------------------------------------------------------------------
- // setSortDirection
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setSortDirection( MiscCoord_V x, MiscSortDirection n )
- {
- MISC_RANGE_CHECK( x );
- MISC_ENUM_CHECK( n, MISC_SORT_DIR_MAX );
- if (sort_dirs == 0) alloc_sort_dirs();
- sort_dirs[x] = n;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // alloc_sort_types
- //-----------------------------------------------------------------------------
- void MiscTableBorder::alloc_sort_types()
- {
- sort_types = (MiscSortType*) do_alloc_init( sizeof(*sort_types) );
- }
-
-
- //-----------------------------------------------------------------------------
- // setSortType
- //-----------------------------------------------------------------------------
- void MiscTableBorder::setSortType( MiscCoord_V x, MiscSortType n )
- {
- MISC_RANGE_CHECK( x );
- MISC_ENUM_CHECK( n, MISC_SORT_TYPE_MAX );
- if (sort_types == 0) alloc_sort_types();
- sort_types[x] = n;
- }
-
-
- //-----------------------------------------------------------------------------
- // isSlotSelected
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::slotIsSelected( MiscCoord_P s ) const
- {
- return (s >= 0 && s < num_slots ?
- selection.contains(physicalToVisual(s)) : false);
- }
-
-
- //-----------------------------------------------------------------------------
- // selectedSlot
- //-----------------------------------------------------------------------------
- MiscCoord_P MiscTableBorder::selectedSlot() const
- {
- MiscCoord_V const s = selection.getCursor();
- return (s >= 0 && s < num_slots ? visualToPhysical(s) : -1);
- }
-
-
- //-----------------------------------------------------------------------------
- // selectSlot
- //-----------------------------------------------------------------------------
- void MiscTableBorder::selectSlot( MiscCoord_P s )
- {
- MISC_RANGE_CHECK( s );
- selection.add( physicalToVisual(s) );
- }
-
-
- //-----------------------------------------------------------------------------
- // selectedSlots
- //-----------------------------------------------------------------------------
- bool MiscTableBorder::hasMultipleSelection() const
- {
- bool ret = false;
- if (hasSelection())
- {
- MiscCoord_V lo, hi;
- selection.getTotalRange( lo, hi );
- ret = (hi > lo);
- }
- return ret;
- }
-
-
- //-----------------------------------------------------------------------------
- // selectedSlots
- //-----------------------------------------------------------------------------
- void MiscTableBorder::selected_slots(MiscIntList* list, bool do_tags) const
- {
- [list empty];
- for (unsigned int i = 0, lim = selection.numRanges(); i < lim; i++)
- {
- MiscCoord_V lo, hi;
- selection.getRangeAt( i, lo, hi );
- for ( ; lo <= hi; lo++)
- [list addInt: (do_tags ? getTag(lo) : visualToPhysical(lo))];
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // selectSlots
- //-----------------------------------------------------------------------------
- void MiscTableBorder::selectSlots( MiscIntList* list )
- {
- for (int i = [list count]; i-- > 0; )
- selection.add( physicalToVisual([list intAt:i]) );
- }
-
-
- //-----------------------------------------------------------------------------
- // selectTags
- // FIXME: Sort the incoming list and do binary instead of linear search.
- //-----------------------------------------------------------------------------
- void MiscTableBorder::selectTags( MiscIntList* list )
- {
- unsigned int const lim = [list count];
- if (lim > 0)
- {
- unsigned int i;
- int* inTags = (int*)malloc( lim * sizeof(int) );
- for (i = 0; i < lim; i++)
- inTags[i] = [list intAt:i];
-
- for (int j = count(); j-- > 0; )
- {
- int const t = getTag(j); // MiscCoord_V
- for (i = lim; i-- > 0; )
- {
- if (t == inTags[i])
- {
- selection.add(j); // MiscCoord_V
- break;
- }
- }
- }
- free( inTags );
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // MiscTableSlot::read
- //-----------------------------------------------------------------------------
- void MiscTableSlot::read( NXTypedStream* stream )
- {
- NXReadType( stream, @encode(MiscPixels), &size );
- NXReadType( stream, @encode(MiscPixels), &min_size );
- NXReadType( stream, @encode(MiscPixels), &max_size );
- NXReadType( stream, @encode(MiscPixels), &data_size );
- NXReadType( stream, @encode(MiscTableSizing), &sizing );
- MISC_ENUM_CHECK( sizing, MISC_MAX_SIZING );
- offset = 0;
- adj_size = size;
- }
-
-
- //-----------------------------------------------------------------------------
- // MiscTableSlot::write
- //-----------------------------------------------------------------------------
- void MiscTableSlot::write( NXTypedStream* stream )
- {
- NXWriteType( stream, @encode(MiscPixels), &size );
- NXWriteType( stream, @encode(MiscPixels), &min_size );
- NXWriteType( stream, @encode(MiscPixels), &max_size );
- NXWriteType( stream, @encode(MiscPixels), &data_size );
- NXWriteType( stream, @encode(MiscTableSizing), &sizing );
- }
-
-
- //-----------------------------------------------------------------------------
- // write
- //-----------------------------------------------------------------------------
- void MiscTableBorder::write( NXTypedStream* stream )
- {
- int zero = 0;
-
- NXWriteType( stream, @encode(MiscBorderType), &type );
- NXWriteObjectReference( stream, owner );
- def_slot.write( stream );
- NXWriteType( stream, @encode(int), &num_slots );
-
- if (slots != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- slots[i].write(stream);
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- if (v2p != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(MiscCoord_P), &(v2p[i]) );
- for (int j = 0; j < num_slots; j++)
- NXWriteType( stream, @encode(MiscCoord_V), &(p2v[j]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- NXWriteType( stream, @encode(int), &def_tag );
- if (tags != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(int), &(tags[i]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- NXWriteType( stream, @encode(MiscPixels), &uniform_size );
- NXWriteType( stream, @encode(MiscPixels), &min_total_size );
- NXWriteType( stream, @encode(MiscPixels), &max_total_size );
- NXWriteType( stream, @encode(int), &num_springy );
- NXWriteType( stream, @encode(MiscTableTitleMode), &title_mode );
-
- if (titles != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(char*), &(titles[i]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- NXWriteType( stream, @encode(MiscTableCellStyle), &def_style );
- if (styles != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(MiscTableCellStyle), &(styles[i]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- // Cannot archive sort_funcs -- it's the address of a function.
-
- if (prototypes != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteObject( stream, prototypes[i] );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- if (sort_dirs != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(MiscSortDirection), &(sort_dirs[i]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- if (sort_types != 0)
- {
- NXWriteType( stream, @encode(int), &num_slots );
- for (int i = 0; i < num_slots; i++)
- NXWriteType( stream, @encode(MiscSortType), &(sort_types[i]) );
- }
- else
- NXWriteType( stream, @encode(int), &zero );
-
- NXWriteType( stream, @encode(bool), &selectable );
- NXWriteType( stream, @encode(bool), &sizeable );
- NXWriteType( stream, @encode(bool), &draggable );
- NXWriteType( stream, @encode(bool), &modifier_drag );
-
- needs_recalc = true;
- }
-
-
- //-----------------------------------------------------------------------------
- // read
- //-----------------------------------------------------------------------------
- void MiscTableBorder::read( NXTypedStream* stream )
- {
- int n;
- emptyAndFree();
-
- NXReadType( stream, @encode(MiscBorderType), &type );
- MISC_ENUM_CHECK( type, MISC_MAX_BORDER );
- owner = NXReadObject( stream );
- def_slot.read( stream );
- NXReadType( stream, @encode(int), &num_slots );
- max_slots = num_slots;
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_slots();
- for (int i = 0; i < num_slots; i++)
- slots[i].read(stream);
- }
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_vmap();
- for (int i = 0; i < num_slots; i++)
- NXReadType( stream, @encode(MiscCoord_P), &(v2p[i]) );
- for (int j = 0; j < num_slots; j++)
- NXReadType( stream, @encode(MiscCoord_V), &(p2v[j]) );
- }
-
- NXReadType( stream, @encode(int), &def_tag );
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_tags();
- for (int i = 0; i < num_slots; i++)
- NXReadType( stream, @encode(int), &(tags[i]) );
- }
-
- NXReadType( stream, @encode(MiscPixels), &uniform_size );
- NXReadType( stream, @encode(MiscPixels), &min_total_size );
- NXReadType( stream, @encode(MiscPixels), &max_total_size );
- NXReadType( stream, @encode(int), &num_springy );
- NXReadType( stream, @encode(MiscTableTitleMode), &title_mode );
- MISC_ENUM_CHECK( title_mode, MISC_MAX_TITLE );
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_titles();
- for (int i = 0; i < num_slots; i++)
- NXReadType( stream, @encode(char*), &(titles[i]) );
- }
-
- NXReadType( stream, @encode(MiscTableCellStyle), &def_style );
- MISC_ENUM_CHECK( def_style, MISC_TABLE_CELL_MAX );
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_styles();
- for (int i = 0; i < num_slots; i++)
- {
- NXReadType( stream, @encode(MiscTableCellStyle), &(styles[i]) );
- MISC_ENUM_CHECK( styles[i], MISC_TABLE_CELL_MAX );
- }
- }
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_prototypes();
- for (int i = 0; i < num_slots; i++)
- prototypes[i] = NXReadObject(stream);
- }
-
- // Cannot archive sort_funcs, they are function addresses.
- sort_funcs = 0;
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_sort_dirs();
- for (int i = 0; i < num_slots; i++)
- {
- NXReadType( stream, @encode(MiscSortDirection), &(sort_dirs[i]) );
- MISC_ENUM_CHECK( sort_dirs[i], MISC_SORT_DIR_MAX );
- }
- }
-
- NXReadType( stream, @encode(int), &n );
- if (n != 0)
- {
- alloc_sort_types();
- for (int i = 0; i < num_slots; i++)
- {
- NXReadType( stream, @encode(MiscSortType), &(sort_types[i]) );
- MISC_ENUM_CHECK( sort_types[i], MISC_SORT_TYPE_MAX );
- }
- }
-
- NXReadType( stream, @encode(bool), &selectable );
- NXReadType( stream, @encode(bool), &sizeable );
- NXReadType( stream, @encode(bool), &draggable );
- NXReadType( stream, @encode(bool), &modifier_drag );
- needs_recalc = true;
- }
-
-
- //-----------------------------------------------------------------------------
- // Constructor
- //-----------------------------------------------------------------------------
- MiscTableBorder::MiscTableBorder( MiscBorderType x )
- {
- MISC_ENUM_CHECK( x, MISC_MAX_BORDER );
- memset( this, 0, sizeof(*this) );
- type = x;
- max_total_size = MISC_MAX_PIXELS_SIZE;
- clearCursor();
-
- if (type == MISC_ROW_BORDER)
- {
- uniform_size = 18;
- def_slot.offset = 0;
- def_slot.size = uniform_size;
- def_slot.min_size = 10;
- def_slot.max_size = MISC_MAX_PIXELS_SIZE;
- def_slot.data_size = 0;
- def_slot.sizing = MISC_NUSER_NDATA_NSPRINGY_SIZING;
- title_mode = MISC_NUMBER_TITLE;
- draggable = false;
- modifier_drag = true;
- sizeable = false;
- selectable = true;
- }
- else
- {
- def_slot.offset = 0;
- def_slot.size = 80;
- def_slot.min_size = 10;
- def_slot.max_size = MISC_MAX_PIXELS_SIZE;
- def_slot.data_size = 0;
- def_slot.sizing = MISC_USER_NDATA_NSPRINGY_SIZING;
- uniform_size = 0;
- title_mode = MISC_CUSTOM_TITLE;
- draggable = true;
- modifier_drag = false;
- sizeable = true;
- selectable = false;
- }
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Destructor
- //-----------------------------------------------------------------------------
- MiscTableBorder::~MiscTableBorder()
- {
- emptyAndFree();
- }
-